/*
 * @Description: 定义接口
 * @Autor: HuiSir<273250950@qq.com>
 * @Date: 2021-04-30 15:45:14
 * @LastEditTime: 2021-05-06 09:34:48
 */

/**
 * 接口以`interface`关键字开始，每个接口都有一个接口名
 * 接口定义必须在`{}`花括号中
 * 接口在编译为js后会消失，只在ts中有效
 * 接口只是定义规范，接口中无法赋值
 * 接口只能定义为是对象、类、函数类型，不能定义基本数据类型（基本类型可以用自定义类型type）
 * 接口中只要有定义的数据类型，在实现这个接口的类、对象或函数中就必须遵循这个规范，属性不能多也不能少
 * 可以使用`readonly`修饰只读属性/方法，使用`?`号修饰非必须属性/方法
 */

/* 对象/class类 接口 */
interface Obj {
    readonly id: number | string
    name: string
    age: number
    sex: string
    getName?: () => string
    setName(name: string): void
}

/**
 * 函数接口
 * 就是一個只有參數類型和返回值類型的函數定義
 * 參數列表裏的每一個參數都要有名稱和類型
 */
interface Fn {
    (arg1: number, arg2: number): number
}

/**
 * 对象实现接口
 * 实现了接口的对象中可以省略属性的类型（因为在接口中已做了限制）
 * 只读属性只能在初始化时赋值
 */
const persion: Obj = {
    id: Date.now(),
    name: "小明",
    age: 12,
    sex: "男",
    setName(name) {
        this.name = name
    }
}

// persion.id=1 // 报错：无法分配到 "id" ，因为它是只读属性。

/**
 * 函数实现接口
 */
const add: Fn = function (a: number, b: number): number {
    return a + b
}

/**
 * 定义可索引类型的接口，用于对象，否则对象不可使用`对象名['key']`开取值
 * ts目前只支持key为string和number类型的索引
 * 数组本身是可引索的值，不需要声明接口)
 */
interface IMethods {
    [key: string]: (...arg: any[]) => any
}

const methods: IMethods = {
    getName(){
		return "zhangsan"
	}
}

console.log(methods["getName"]())